package com.hunter.api.handler;

import com.alibaba.fastjson.JSONObject;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.hunter.api.bean.TokenBean;
import com.hunter.api.bean.UserBean;
import com.hunter.api.help.AESHelper;
import com.hunter.api.help.DateHelper;
import com.hunter.api.help.result.ErrorHelp;
import com.hunter.api.help.JsonHelper;
import com.hunter.api.mapper.TokenMapper;
import com.hunter.api.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
 * @author HunterHuang
 * @version 1.0
 * @ClassName TokenHandler
 * @date 2019/5/31 17:24
 */
@Slf4j
@Service
public class TokenHandler {

    @Autowired
    private TokenMapper tokenMapper;

    @Autowired
    private UserMapper userMapper;

    private String TOKEN_KEY_UUID = "uuid";
    @Value("${token.timeout}")
    private long timeout;
    @Value("${token.key}")
    private String key;
    private static final String TOKEN_KEY_SECRET = "secret";
    private static final String TOKEN_KEY_TIMESTAMP = "ts";




    public JSONObject getToken(String token, UserBean user){
        JSONObject json =new JSONObject();
        token= JWT.create().withAudience(user.getId().toString())
                .sign(Algorithm.HMAC256(user.getPassword()+ DateHelper.currentTimeSeconds()));
        if (token==null||token.equals("")){
            return ErrorHelp.TOKEN_GET_FAILED ;
        }
        json.put("token",token);
        writeToken(token,user.getId());
        return json;
    }

    public JSONObject writeToken(String token,Long id){
        TokenBean tokenBean =new TokenBean();
        JSONObject json =new JSONObject();
        if (token==null||token.equals("")){
            return ErrorHelp.TOKEN_NOT_EXIST ;
        }
        tokenBean.setToken(token);
        tokenBean.setUser_id(id);
        tokenBean.setExpires_time(DateHelper.currentTimeSeconds());
        tokenMapper.insert(tokenBean);
        json.put("token",token);
        return json ;
    }

    public JSONObject cheakToecn(String token){
        TokenBean tokenBean =new TokenBean();
        JSONObject json =new JSONObject();
        try {
            if (token == null) {
                json = ErrorHelp.TOKEN_NOT_EXIST;
                return json;
            }
            Long userId = Long.valueOf(JWT.decode(token).getAudience().get(0));
            log.info("userId : ",userId);
            log.info("token : ",token);
            tokenBean.setToken(token);
            tokenBean.setUser_id(userId);
            tokenBean = tokenMapper.cheakToecn(tokenBean);
            if (tokenBean==null) {
                json = ErrorHelp.TOKEN_NOT_EXIST;
                return json;
            }
            log.info("getExpires_time:"+tokenBean.getExpires_time());
            log.info("timeout:"+timeout);
            if ((tokenBean.getExpires_time()<(DateHelper.currentTimeSeconds()-timeout)|| tokenBean.getExpires_time() == 0l )) {
                json = ErrorHelp.TOKEN_OUT_ERROR;
                return json;
            }
            UserBean user = userMapper.userInfo(userId);
            if (user == null) {
                json = ErrorHelp.USER_NOT_EXISTS;
                return json;
            }
            json.put("id",userId);
            tokenBean.setExpires_time(DateHelper.currentTimeSeconds());
            tokenMapper.update(tokenBean);
        }catch (Exception e){
            json = ErrorHelp.TOKEN_ERROR;
        }finally {
            return json;
        }

    }

    /**
     * 解密token，并检查内容
     * 解密不成功，未找到相应的数据，过期了，都返回null
     * 成功后，返回包含解密后数据的JsonObject
     *
     * @param token   token
     * @param timeout 超时时长，单位：s
     * @return null或包含解密后数据的JsonObject
     */
    private TokenBean parseToken(String token, String key, long timeout) {

        String data = AESHelper.decrypt(token, key);

        JSONObject tokenObj = null;
        try {
            tokenObj = JSONObject.parseObject(data);
        } catch (Exception ex) {
            //解析为json出错
        }

        if (tokenObj == null) {
            return null;
        }

        long timestamp = JsonHelper.getLong(tokenObj,TOKEN_KEY_TIMESTAMP, 0L);
        String uuid = JsonHelper.getString(tokenObj,TOKEN_KEY_UUID, "");
        String secret = JsonHelper.getString(tokenObj,TOKEN_KEY_SECRET, "");
        if (timestamp == 0L || StringUtils.isBlank(uuid) || StringUtils.isBlank(secret)) {
            //未解出需要的数据
            return null;
        }

        if (timeout > 0L && DateHelper.currentTimeSeconds() - timestamp > timeout) {
            //过期了
            return null;
        }

        //检查uuid是否黑名单？ todo：app中配置，需要缓存住 （暂缓）

        return new TokenBean();
    }
}
